package com.civicscience;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.MalformedURLException;
import java.util.ArrayList;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.WindowManager;
import android.view.View.OnClickListener;
import android.view.Window;
import android.widget.Button;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

import com.facebook.android.*;
import com.facebook.android.AsyncFacebookRunner.RequestListener;
import com.facebook.android.Facebook.*;
import com.civicscience.R;

public class FacebookActivity extends Activity {

	public static final String APP_ID = "129840303769814";
	private final ArrayList<Friend> friends = new ArrayList<Friend>();
	private static final String[] PERMISSIONS = new String[] {
			"publish_stream", "read_stream", "offline_access", "user_about_me",
			"user_birthday" };

	private TextView mText;
	private ListView listView;
	private Facebook facebook;
	private AsyncFacebookRunner asyncRunner;
	private Handler mHandler = new Handler();
	private ProgressDialog mSpinner;
	private FriendsArrayAdapter friendsArrayAdapter;
	private Activity activity = this;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		requestWindowFeature( Window.FEATURE_NO_TITLE );
		getWindow().addFlags( WindowManager.LayoutParams.FLAG_FULLSCREEN );
		
		if (APP_ID == null) {
			Util.showAlert(this, "Warning",
					"Facebook Application ID must be set...");
		}

		// Initialize the content view
		setContentView(R.layout.main);
		// Get the status text line resource
		mText = (TextView) findViewById(R.id.txt);

		// Setup the ListView Adapter that is loaded when selecting
		// "get friends"
		listView = (ListView) findViewById(R.id.friendsview);
		friendsArrayAdapter = new FriendsArrayAdapter(this, R.layout.list,
				friends);
		listView.setAdapter(friendsArrayAdapter);

		// Define a spinner used when loading the friends over the network
		mSpinner = new ProgressDialog(listView.getContext());
		mSpinner.requestWindowFeature(Window.FEATURE_NO_TITLE);
		mSpinner.setMessage("Loading...");

		// Initialize the Facebook session
		facebook = new Facebook(APP_ID);
		asyncRunner = new AsyncFacebookRunner(facebook);

		facebook.authorize(this, PERMISSIONS, new LoginDialogListener());
		asyncRunner.request("me", new UserInfoRequestListener());

	}

	@Override
	public void onActivityResult(int requestCode, int resultCode, Intent data) {
		super.onActivityResult(requestCode, resultCode, data);
		Log.d("FB App", "onActivityResult(): " + requestCode);
		facebook.authorizeCallback(requestCode, resultCode, data);
	}

	// Menu handlers

	/**
	 * Invoked at the time to create the menu
	 * 
	 * @param menu
	 *            is the menu to create
	 */
	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		MenuInflater inflater = getMenuInflater();
		inflater.inflate(R.layout.menu, menu);
		return true;
	}

	/**
	 * Invoked when preparing to display the menu
	 * 
	 * @param menu
	 *            is the menu to prepare
	 */
	@Override
	public boolean onPrepareOptionsMenu(Menu menu) {

		MenuItem loginItem = menu.findItem(R.id.login);
		MenuItem postItem = menu.findItem(R.id.wallpost);
		MenuItem getfriendsItem = menu.findItem(R.id.getfriends);
		if (facebook.isSessionValid()) {
			loginItem.setTitle("Logout");
			postItem.setEnabled(true);
			getfriendsItem.setEnabled(true);
		} else {
			loginItem.setTitle("Login");
			postItem.setEnabled(false);
			getfriendsItem.setEnabled(false);
		}
		loginItem.setEnabled(true);
		return super.onPrepareOptionsMenu(menu);
	}

	/**
	 * Invoked when a menu item has been selected
	 * 
	 * @param item
	 *            is the selected menu items
	 */
	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		switch (item.getItemId()) {

		// Login/logout toggle
		case R.id.login:
			// Toggle the button state.
			// If coming from login transition to logout.
			if (facebook.isSessionValid()) {
				AsyncFacebookRunner asyncRunner = new AsyncFacebookRunner(
						facebook);
				asyncRunner.logout(this.getBaseContext(),
						new LogoutRequestListener());
			} else {
				// Toggle the button state.
				// If coming from logout transition to login (authorize).
				facebook.authorize(this, PERMISSIONS, new LoginDialogListener());
				asyncRunner.request("me", new UserInfoRequestListener());
			}
			break;

		// Wall Post
		case R.id.wallpost: // Wall Post
			facebook.dialog(this, "stream.publish",
					new WallPostDialogListener());
			break;

		// Get Friend's List
		case R.id.getfriends: // Wall Post
			// Get the authenticated user's friends
			mSpinner.show();
			asyncRunner.request("me/friends", new FriendsRequestListener());
			break;
		
		// Social graph
		case R.id.socialgraph:
			Intent intent = new Intent();
			intent.setAction("graph");
			startActivity(intent);
			break;
		default:
			return false;

		}
		return true;
	}

	// ////////////////////////////////////////////////////////////////////
	// Get Friends request listener
	// ////////////////////////////////////////////////////////////////////

	/**
	 * FriendsRequestListener implements a request lister/callback for
	 * "get friends" requests
	 */
	public class FriendsRequestListener implements
			com.facebook.android.AsyncFacebookRunner.RequestListener {

		/**
		 * Called when the request to get friends has been completed. Retrieve
		 * and parse and display the JSON stream.
		 */
		@Override
		public void onComplete(String response, Object state) {
			try {
				// process the response here: executed in background thread
				Log.d("Facebook-Example-Friends Request", "response.length(): "
						+ response.length());
				Log.d("Facebook-Example-Friends Request", "Response: "
						+ response);

				final JSONObject json = new JSONObject(response);
				JSONArray d = json.getJSONArray("data");
				int l = (d != null ? d.length() : 0);
				Log.d("Facebook-Example-Friends Request", "d.length(): " + l);

				for (int i = 0; i < l; i++) {
					JSONObject o = d.getJSONObject(i);
					String n = o.getString("name");
					String id = o.getString("id");

					Friend f = new Friend();
					try {
						f.setId(id);
						f.setName(n);
						friends.add(f);
					} catch (IOException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}

				// Only the original owner thread can touch its views
				runOnUiThread(new Runnable() {
					public void run() {
						friendsArrayAdapter = new FriendsArrayAdapter(activity,
								R.layout.list, friends);
						listView.setAdapter(friendsArrayAdapter);
						friendsArrayAdapter.notifyDataSetChanged();
						mSpinner.dismiss();
					}
				});
			} catch (JSONException e) {
				Log.w("Facebook-Example", "JSON Error in response");
			}
		}

		@Override
		public void onIOException(IOException e, Object state) {
			// TODO Auto-generated method stub

		}

		@Override
		public void onFileNotFoundException(FileNotFoundException e,
				Object state) {
			// TODO Auto-generated method stub

		}

		@Override
		public void onMalformedURLException(MalformedURLException e,
				Object state) {
			// TODO Auto-generated method stub

		}

		@Override
		public void onFacebookError(FacebookError e, Object state) {
			// TODO Auto-generated method stub

		}
	}

	// ////////////////////////////////////////////////////////////////////
	// Wall Post request listener
	// ////////////////////////////////////////////////////////////////////

	/**
	 * WallPostRequestListener implements a request lister/callback for
	 * "wall post requests"
	 */
	public class WallPostRequestListener implements
			com.facebook.android.AsyncFacebookRunner.RequestListener {

		/**
		 * Called when the wall post request has completed
		 */
		public void onComplete(String response, Object state) {
			Log.d("Facebook-Example", "Got response: " + response);
		}

		@Override
		public void onIOException(IOException e, Object state) {
			// TODO Auto-generated method stub

		}

		@Override
		public void onFileNotFoundException(FileNotFoundException e,
				Object state) {
			// TODO Auto-generated method stub

		}

		@Override
		public void onMalformedURLException(MalformedURLException e,
				Object state) {
			// TODO Auto-generated method stub

		}

		@Override
		public void onFacebookError(FacebookError e, Object state) {
			// TODO Auto-generated method stub

		}

	}

	// ////////////////////////////////////////////////////////////////////
	// Wall post dialog completion listener
	// ////////////////////////////////////////////////////////////////////

	/**
	 * WallPostDialogListener implements a dialog lister/callback
	 */
	public class WallPostDialogListener implements
			com.facebook.android.Facebook.DialogListener {

		/**
		 * Called when the dialog has completed successfully
		 */
		public void onComplete(Bundle values) {
			final String postId = values.getString("post_id");
			if (postId != null) {
				Log.d("FB Sample App", "Dialog Success! post_id=" + postId);
				asyncRunner.request(postId, new WallPostRequestListener());
			} else {
				Log.d("FB Sample App", "No wall post made");
			}
		}

		@Override
		public void onCancel() {
			// No special processing if dialog has been canceled
		}

		@Override
		public void onError(DialogError e) {
			// No special processing if dialog has been canceled
		}

		@Override
		public void onFacebookError(FacebookError e) {
			// No special processing if dialog has been canceled
		}
	}

	// ///////////////////////////////////////////////////////
	// Login / Logout Listeners
	// ///////////////////////////////////////////////////////

	/**
	 * Listener for login dialog completion status
	 */
	private final class LoginDialogListener implements
			com.facebook.android.Facebook.DialogListener {

		/**
		 * Called when the dialog has completed successfully
		 */
		public void onComplete(Bundle values) {
			// Process onComplete
			Log.d("FB Sample App", "LoginDialogListener.onComplete()");
			// Dispatch on its own thread
			mHandler.post(new Runnable() {
				public void run() {
					mText.setText("Facebook login successful. Press Menu...");
				}
			});
		}

		/**
         *
         */
		public void onFacebookError(FacebookError error) {
			// Process error
			Log.d("FB Sample App", "LoginDialogListener.onFacebookError()");
		}

		/**
         *
         */
		public void onError(DialogError error) {
			// Process error message
			Log.d("FB Sample App", "LoginDialogListener.onError()");
		}

		/**
         *
         */
		public void onCancel() {
			// Process cancel message
			Log.d("FB Sample App", "LoginDialogListener.onCancel()");
		}
	}

	/**
	 * Listener for logout status message
	 */
	private class LogoutRequestListener implements RequestListener {

		/** Called when the request completes w/o error */
		public void onComplete(String response) {

			// Only the original owner thread can touch its views
			runOnUiThread(new Runnable() {
				public void run() {
					mText.setText("Thanks for using FB Sample App. Bye bye...");
					friends.clear();
					friendsArrayAdapter.notifyDataSetChanged();
				}
			});

			// Dispatch on its own thread
			mHandler.post(new Runnable() {
				public void run() {
				}
			});
		}

		@Override
		public void onComplete(String response, Object state) {
			// TODO Auto-generated method stub

		}

		@Override
		public void onIOException(IOException e, Object state) {
			// TODO Auto-generated method stub

		}

		@Override
		public void onFileNotFoundException(FileNotFoundException e,
				Object state) {
			// TODO Auto-generated method stub

		}

		@Override
		public void onMalformedURLException(MalformedURLException e,
				Object state) {
			// TODO Auto-generated method stub

		}

		@Override
		public void onFacebookError(FacebookError e, Object state) {
			// TODO Auto-generated method stub

		}

	}

	/**
	 * Listener for logout status message
	 */
	private class UserInfoRequestListener implements RequestListener {

		/** Called when the request completes w/o error */
		public void onComplete(String response) {
			mSpinner.dismiss();
			// ?
		}

		@Override
		public void onComplete(String response, Object state) {
			// TODO Auto-generated method stub

		}

		@Override
		public void onIOException(IOException e, Object state) {
			// TODO Auto-generated method stub

		}

		@Override
		public void onFileNotFoundException(FileNotFoundException e,
				Object state) {
			// TODO Auto-generated method stub

		}

		@Override
		public void onMalformedURLException(MalformedURLException e,
				Object state) {
			// TODO Auto-generated method stub

		}

		@Override
		public void onFacebookError(FacebookError e, Object state) {
			// TODO Auto-generated method stub

		}

	}

	public void postMessageOnWall(final String msg) {
		final Activity activity = this;
		
		Thread t = new Thread() {
			public void run() {
				if (facebook.isSessionValid()) {
					Bundle parameters = new Bundle();
					parameters.putString("message", msg);// ?
					try {
						String response = facebook.request("me/feed",
								parameters, "POST");
						System.out.println(response);
					} catch (IOException e) {
						e.printStackTrace();
					}
				} else {
					facebook.authorize(activity, PERMISSIONS,
							new LoginDialogListener());
				}
			}
		};
		t.start();

	}
}